#include "Ball.hpp"
#include "Game.hpp"
#include "Global.hpp"
#include "Helper.hpp"

std::string cubeMapFile[6] = {	"../Resources/Ball/sky.png",	// left
								"../Resources/Ball/sky.png",	// right
								"../Resources/Ball/sky.png",	// bottom
								"../Resources/Ball/sky.png",	// top
								"../Resources/Ball/sky.png",	// front
								"../Resources/Ball/sky.png"};	// back

bool Ball::textureInitialized = false;
GLuint Ball::ballTexture = 0;

Ball::Ball(Game* g, Vector3f v):
	MoveableEntity(g),
	cubeMap(512, 512, radius, 2.0)
{
	cubeMap.setGameReference(g);
	velocity = v;
	radius = 0.2f;

	//Load the Shader
	m_Shader.Load(ResourceDir+"Ball.vert", ResourceDir+"Ball.frag");

	cm=CollisionModel(Vector3f(-radius, -radius, -radius), Vector3f(radius, radius, radius));
	if (!Ball::textureInitialized)
	{/*
		QImage image;
		for (int i = 0; i < 6; i++)
		{
			image.load(cubeMapFile[i]);
			ballTexImage[i] = QGLWidget::convertToGLFormat(image); // ARGB to RGBA
		}
		
		glGenTextures(1,&Ball::ballTexture);
		glBindTexture(GL_TEXTURE_CUBE_MAP, Ball::ballTexture);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 4, ballTexImage[0].width(), ballTexImage[0].height(),
			     0, GL_RGBA, GL_UNSIGNED_BYTE, ballTexImage[0].bits());
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 4, ballTexImage[0].width(), ballTexImage[0].height(),
			     0, GL_RGBA, GL_UNSIGNED_BYTE, ballTexImage[0].bits());
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 4, ballTexImage[0].width(), ballTexImage[0].height(),
			     0, GL_RGBA, GL_UNSIGNED_BYTE, ballTexImage[0].bits());
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 4, ballTexImage[0].width(), ballTexImage[0].height(),
			     0, GL_RGBA, GL_UNSIGNED_BYTE, ballTexImage[0].bits());
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 4, ballTexImage[0].width(), ballTexImage[0].height(),
			     0, GL_RGBA, GL_UNSIGNED_BYTE, ballTexImage[0].bits());
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 4, ballTexImage[0].width(), ballTexImage[0].height(),
			     0, GL_RGBA, GL_UNSIGNED_BYTE, ballTexImage[0].bits());
		
		// Sets the texture's behavior for wrapping (optional)
		glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_REPEAT);
		// Sets the texture's max/min filters (mandatory) 
		glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);*/
	}
}


//time: passed time in seconds
void Ball::onTick(float time)
{
	//cubeMap.render(position);
	manager->MoveEntity(this, time);
}


void Ball::Render()
{
	//cubeMap.enable();

	glPushMatrix();
	glTranslatef(position.x,position.y,radius/2.0f);

	// the angle step used in iteration
	float a = (2.0f*PI)/40.0f;
	float c = 0.0f;

	glActiveTexture(GL_TEXTURE0);
	glEnable(GL_TEXTURE_CUBE_MAP);
	glBindTexture(GL_TEXTURE_CUBE_MAP, Ball::ballTexture); 
	// Enable texture generation for S,T,R coords
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	glEnable(GL_TEXTURE_GEN_R);
	// Sets the coordinates to be generated and how
	glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
	glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
	glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);

	glMatrixMode(GL_TEXTURE);
	glPushMatrix();
	glLoadIdentity();
	float ViewMatrix[16], Inv[16];
	glGetFloatv(GL_MODELVIEW_MATRIX, ViewMatrix);

	ViewMatrix[3] = ViewMatrix[7] = ViewMatrix[11] = ViewMatrix[12] = ViewMatrix[13] = ViewMatrix[14] = 0;
	ViewMatrix[15] = 1;
	InvertMatrix(ViewMatrix, Inv);
	glLoadMatrixf(Inv);
	
	//m_Shader.Set();
	
	glEnable(GL_NORMALIZE);
	for (float theta = 0.0f; theta < PI; theta += a, c += a/2.0f){
		for (float phi = 0.0f; phi < 2.0f*PI; phi +=a){
			float p_1[3] = {radius*sin(theta)*cos(phi+c), radius*sin(theta)*sin(phi+c), radius*cos(theta)};
			float p_2[3] = {radius*sin(theta)*cos(phi+a+c), radius*sin(theta)*sin(phi+a+c), radius*cos(theta)};
			float p_3[3] = {radius*sin(theta+a)*cos(phi+a/2+c), radius*sin(theta+a)*sin(phi+a/2+c), radius*cos(theta+a)};
			float p_4[3] = {radius*sin(theta-a)*cos(phi+a/2+c), radius*sin(theta-a)*sin(phi+a/2+c), radius*cos(theta-a)};
			
			glBegin(GL_TRIANGLES);
				glNormal3fv(p_1);
				glVertex3fv(p_1);
			
				glNormal3fv(p_3);
				glVertex3fv(p_3);

				glNormal3fv(p_2);
				glVertex3fv(p_2);

				glNormal3fv(p_1);
				glVertex3fv(p_1);

				glNormal3fv(p_2);
				glVertex3fv(p_2);

				glNormal3fv(p_4);
				glVertex3fv(p_4);
			glEnd();
		}
	}
	
	glPopMatrix(); // GL_TEXTURE
	//m_Shader.Unset();

	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);
	glDisable(GL_TEXTURE_GEN_R);
	glDisable(GL_TEXTURE_CUBE_MAP);
	//cubeMap.disable();
}



void Ball::setVelocity(Vector3f v)
{
	velocity = v;	
}